﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input;

namespace Brain
{
    public class MenuSystem : IUpdateable, IDisposable
    {
        public MenuEntry[,] Entries;

        public int SelectedX { get; protected set; }
        public int SelectedY { get; protected set; }

        public bool ShouldUpdate { get; set; }

        public IMenuAnimation Animation;

        public event SetMenuEntry OnUpdateMenuEntry;

        public object Tag;

        public event SetVoid OnTransition;

        public bool CanSelect = true;

        public MenuSystem(int XCount, int YCount)
        {
            Entries = new MenuEntry[XCount, YCount];

            ShouldUpdate = true;
        }

        public virtual void TransiteTo(MenuSystem newSystem)
        {
            if (OnTransition != null)
            {
                OnTransition();
            }
        }

        public void SetSelected(int x, int y)
        {
            this.SelectedX = x;
            this.SelectedY = y;
        }

        public void AddEntry(MenuEntry entry, int X, int Y)
        {
            entry.System = this;
            entry.X = X;
            entry.Y = Y;
            this.Entries[X, Y] = entry;
            if (X + 1 > MaxX)
            {
                this.MaxX = X + 1;
            }
            if (Y + 1 > MaxY)
            {
                this.MaxY = Y + 1;
            }
        }
        protected int MaxX;
        protected int MaxY;

        private int Timer;

        public static readonly int TimeToStart = 300;

        public void Update()
        {
            Timer += Engine.Instance.GameTime.ElapsedGameTime.Milliseconds;
            if (Timer > TimeToStart)
            {
                IInputManager input = Engine.Instance.InputManager;

                if (CanSelect)
                {
                    if (input.IsKeyPress(Keys.W) || input.IsKeyPress(Keys.Up) ||
                        input.IsAnyPlayerButtonPress(Buttons.LeftThumbstickUp) || input.IsAnyPlayerButtonPress(Buttons.DPadUp))
                    {
                        SelectedY--;
                    }
                    if (input.IsKeyPress(Keys.S) || input.IsKeyPress(Keys.Down) ||
                        input.IsAnyPlayerButtonPress(Buttons.LeftThumbstickDown) || input.IsAnyPlayerButtonPress(Buttons.DPadDown))
                    {
                        SelectedY++;
                    }
                    if (input.IsKeyPress(Keys.A) || input.IsKeyPress(Keys.Left) ||
                        input.IsAnyPlayerButtonPress(Buttons.LeftThumbstickLeft) || input.IsAnyPlayerButtonPress(Buttons.DPadLeft))
                    {
                        SelectedX--;
                    }
                    if (input.IsKeyPress(Keys.D) || input.IsKeyPress(Keys.Right) ||
                        input.IsAnyPlayerButtonPress(Buttons.LeftThumbstickRight) || input.IsAnyPlayerButtonPress(Buttons.DPadRight))
                    {
                        SelectedX++;
                    }
                }

                SelectedX = IntUtil.Clamp(SelectedX, 0, this.MaxX - 1);
                SelectedY = IntUtil.Clamp(SelectedY, 0, this.MaxY - 1);

                bool select = false;
                if (CanSelect)
                {
                    if (input.IsKeyPress(Keys.Enter) ||
                        input.IsAnyPlayerButtonPress(Buttons.A))
                    {
                        select = true;
                    }
                }

                for (int x = 0; x < MaxX; x++)
                {
                    for (int y = 0; y < MaxY; y++)
                    {
                        MenuEntry entry = this.Entries[x, y];
                        if (entry != null)
                        {
                            if (select && x == SelectedX && y == SelectedY)
                            {
                                entry.Selected();
                            }
                            if (Animation != null)
                            {
                                if (x == SelectedX && y == SelectedY)
                                {
                                    Animation.UpdateSelected(entry);
                                }
                                else
                                {
                                    Animation.UpdateNotSelected(entry);
                                }
                            }
                            entry.Update();
                            if (OnUpdateMenuEntry != null)
                            {
                                OnUpdateMenuEntry(entry);
                            }
                        }
                    }
                }
            }
        }

        public void Dispose()
        {
            this.Entries = null;
            this.Animation = null;
            this.MaxX = -1;
            this.MaxY = -1;
            this.SelectedX = -1;
            this.SelectedY = -1;
            this.ShouldUpdate = false;
        }
    }
}
